/*
 * StateMachine.java
 *
 * Created on March 27, 2007, 3:24 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package ai9hells.pgaibe.common.fsm;

import ai9hells.pgaibe.common.messaging.Telegram;

/**
 *
 * @author andre.bandarra
 */
public class StateMachine<T> {
    private T owner;
    private State<T> currentState = null;
    private State<T> previousState = null;
    private State<T> globalState = null;
    /** Creates a new instance of StateMachine */
    public StateMachine(T owner) {
        this.owner = owner;
    }
    
    public void setCurrentState(State<T> state){
        this.currentState = state;
    }
    
    public State<T> getCurrentState(){
        return currentState;
    }
    public void setGlobalState(State<T> state){
        this.globalState = state;
    }
    public State<T> getGlobalState(){
        return globalState;
    }
    
    public void setPreviousState(State<T> state){
        this.previousState = state;
    }

    public State<T> getPreviousState(){
        return previousState;
    } 
    
    public void update(){
        if (globalState != null){
            globalState.execute(owner);
        }
        if (currentState != null){
            currentState.execute(owner);
        }
    }
    
    public boolean handleMessage(Telegram msg){
        if (globalState != null && globalState.onMessage(owner, msg)){
            return true;
        }
        if (currentState != null && currentState.onMessage(owner, msg)){
            return true;
        }
        return false;
    }
    
    public void changeState(State<T> newState){
        if (newState == null){
            throw new IllegalArgumentException("<StateMachine::ChangeState>:trying to assign null state to current");
        }
        previousState = currentState;
        currentState.exit(owner);
        currentState = newState;
        currentState.enter(owner);
    }
    
    public void revertToPreviousState(){
        changeState(previousState);
    }
    
    public boolean isInState(State<T> state){
        if (state.getClass().equals(currentState.getClass())){
            return true;
        } return false;
    }
    
    public String getNameOfCurrentState(){
        return currentState.getClass().getName();
    }
    
}
